package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"

	"crongo/internal/i18n"
	"crongo/internal/model"
)

var (
	group       = flag.String("g", "default", "指定任务分组")
	status      = flag.Int("s", 1, "指定任务状态(1:启用 2:禁用)")
	list        = flag.Bool("l", false, "列出所有任务")
	listGroup   = flag.String("lg", "", "列出指定分组的任务")
	remove      = flag.Uint("rm", 0, "删除指定ID的任务")
	info        = flag.Uint("i", 0, "查看指定ID的任务详情")
	export      = flag.Bool("export", false, "导出所有任务为crontab格式")
	exportGroup = flag.String("export-group", "", "导出指定分组的任务为crontab格式")
	exportAll   = flag.Bool("export-all", false, "导出所有状态（包括禁用）的任务")
	exportFrom  = flag.String("from", "", "导出指定开始时间之后创建的任务 (格式: 2006-01-02)")
	exportTo    = flag.String("to", "", "导出指定结束时间之前创建的任务 (格式: 2006-01-02)")
	msg         *i18n.Message
)

func init() {
	// 初始化国际化支持
	if err := i18n.InitMessages(); err != nil {
		fmt.Fprintf(os.Stderr, "Failed to initialize i18n: %v\n", err)
		os.Exit(1)
	}

	// 检测系统语言
	lang := i18n.DetectLanguage()
	msg = i18n.GetMessage(lang)
}

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	flag.Parse()

	// 初始化数据库连接
	db, err := gorm.Open(sqlite.Open("crongo.db"), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatalf("连接数据库失败: %v", err)
	}

	// 处理命令行参数
	switch {
	case *export || *exportGroup != "":
		from, to := parseTimeRange(*exportFrom, *exportTo)
		exportTasks(db, *exportGroup, *exportAll, from, to)
		return
	case *list:
		listTasks(db, "")
		return
	case *listGroup != "":
		listTasks(db, *listGroup)
		return
	case *remove > 0:
		removeTask(db, *remove)
		return
	case *info > 0:
		showTaskInfo(db, *info)
		return
	}

	// 如果没有其他参数，则从标准输入读取crontab内容
	importTasks(db, *group, *status)
}

// 解析时间范围
func parseTimeRange(fromStr, toStr string) (from, to time.Time) {
	if fromStr != "" {
		var err error
		from, err = time.ParseInLocation("2006-01-02", fromStr, time.Local)
		if err != nil {
			log.Fatalf("开始时间格式错误: %v", err)
		}
	}
	if toStr != "" {
		var err error
		to, err = time.ParseInLocation("2006-01-02", toStr, time.Local)
		if err != nil {
			log.Fatalf("结束时间格式错误: %v", err)
		}
		// 设置结束时间为当天的最后一秒
		to = to.Add(24*time.Hour - time.Second)
	}
	return
}

// 导入任务
func importTasks(db *gorm.DB, group string, status int) {
	scanner := bufio.NewScanner(os.Stdin)
	var lastComment string
	var lastTaskID uint
	var lastTaskName string
	lineNum := 0

	for scanner.Scan() {
		lineNum++
		line := strings.TrimSpace(scanner.Text())

		if line == "" {
			continue
		}

		// 跳过日志输出行
		if strings.Contains(line, "/Users/") || strings.Contains(line, "[rows:") {
			continue
		}

		// 处理注释行
		if strings.HasPrefix(line, "#") {
			commentLine := strings.TrimSpace(strings.TrimPrefix(line, "#"))

			// 尝试解析任务ID和名称
			if strings.HasPrefix(commentLine, "任务ID:") {
				parts := strings.Split(commentLine, ",")
				if len(parts) >= 2 {
					idStr := strings.TrimSpace(strings.TrimPrefix(parts[0], "任务ID:"))
					namePart := strings.TrimSpace(strings.TrimPrefix(parts[1], "名称:"))
					fmt.Sscanf(idStr, "%d", &lastTaskID)
					lastTaskName = strings.TrimSpace(strings.Split(namePart, ",")[0])
				}
				continue
			}

			// 如果不是任务ID行，则作为描述
			if !strings.Contains(commentLine, "由 CronGo 导出") &&
				!strings.Contains(commentLine, "导出时间:") &&
				!strings.Contains(commentLine, "任务分组:") &&
				!strings.Contains(commentLine, "创建时间范围:") &&
				!strings.Contains(commentLine, "包含所有状态的任务") {
				lastComment = commentLine
			}
			continue
		}

		// 跳过被注释的任务命令行
		if strings.HasPrefix(line, "#") {
			continue
		}

		fields := strings.Fields(line)
		if len(fields) < 6 {
			log.Printf("第 %d 行格式错误，跳过: %s", lineNum, line)
			continue
		}

		cronExpr := strings.Join(fields[0:5], " ")
		command := strings.Join(fields[5:], " ")

		// 检查是否存在相同的任务
		var existingTask model.Task
		err := db.Where("cron_expr = ? AND command = ?", cronExpr, command).First(&existingTask).Error
		if err == nil {
			log.Printf("跳过重复任务 [%s]: 已存在相同的定时表达式和命令", command)
			continue
		}

		// 如果有任务ID，检查是否存在相同ID的任务
		if lastTaskID > 0 {
			var idTask model.Task
			err := db.First(&idTask, lastTaskID).Error
			if err == nil {
				log.Printf("跳过重复任务 [ID:%d]: 已存在相同ID的任务", lastTaskID)
				lastTaskID = 0
				lastTaskName = ""
				continue
			}
		}

		name := lastTaskName
		if name == "" {
			name = command
			if len(name) > 20 {
				name = name[:20]
			}
			name = strings.ReplaceAll(name, " ", "_")
		}

		task := model.Task{
			ID:        lastTaskID,
			Name:      name,
			GroupName: group,
			Command:   command,
			CronExpr:  cronExpr,
			Status:    status,
		}

		if lastComment != "" {
			task.Description = lastComment
			lastComment = ""
		}

		if err := db.Create(&task).Error; err != nil {
			log.Printf("创建任务失败 [%s]: %v", name, err)
			continue
		}

		fmt.Printf("成功创建任务 [ID:%d] [%s]: %s\n", task.ID, name, command)
		lastTaskID = 0
		lastTaskName = ""
	}

	if err := scanner.Err(); err != nil {
		log.Fatalf("读取输入失败: %v", err)
	}
}

// 列出任务
func listTasks(db *gorm.DB, group string) {
	var tasks []model.Task
	query := db
	if group != "" {
		query = query.Where("group_name = ?", group)
	}
	if err := query.Find(&tasks).Error; err != nil {
		log.Fatalf("查询任务失败: %v", err)
	}

	if len(tasks) == 0 {
		fmt.Println("没有找到任务")
		return
	}

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "ID\t名称\t分组\t状态\t上次执行时间\t表达式\t命令\t")
	fmt.Fprintln(w, "--\t----\t----\t----\t----------\t------\t----\t")

	for _, task := range tasks {
		status := "禁用"
		if task.Status == 1 {
			status = "启用"
		}
		lastRun := "-"
		if !task.LastRunTime.IsZero() {
			lastRun = task.LastRunTime.Format("2006-01-02 15:04:05")
		}
		fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
			task.ID, task.Name, task.GroupName, status, lastRun, task.CronExpr, task.Command)
	}
	w.Flush()
}

// 删除任务
func removeTask(db *gorm.DB, id uint) {
	var task model.Task
	if err := db.First(&task, id).Error; err != nil {
		log.Fatalf("任务不存在: %v", err)
		return
	}

	if err := db.Delete(&task).Error; err != nil {
		log.Fatalf("删除任务失败: %v", err)
		return
	}

	fmt.Printf("成功删除任务 [ID:%d] [%s]\n", task.ID, task.Name)
}

// 显示任务详情
func showTaskInfo(db *gorm.DB, id uint) {
	var task model.Task
	if err := db.First(&task, id).Error; err != nil {
		log.Fatalf("任务不存在: %v", err)
		return
	}

	fmt.Println("\n任务详情:")
	fmt.Printf("ID: %d\n", task.ID)
	fmt.Printf("名称: %s\n", task.Name)
	fmt.Printf("分组: %s\n", task.GroupName)
	status := "禁用"
	if task.Status == 1 {
		status = "启用"
	}
	fmt.Printf("状态: %s\n", status)
	fmt.Printf("Cron表达式: %s\n", task.CronExpr)
	fmt.Printf("命令: %s\n", task.Command)
	if task.Description != "" {
		fmt.Printf("描述: %s\n", task.Description)
	}
	if !task.LastRunTime.IsZero() {
		fmt.Printf("上次执行: %s\n", task.LastRunTime.Format("2006-01-02 15:04:05"))
	}
	fmt.Printf("创建时间: %s\n", task.CreatedAt.Format("2006-01-02 15:04:05"))
	fmt.Printf("更新时间: %s\n\n", task.UpdatedAt.Format("2006-01-02 15:04:05"))
}

// 导出任务为crontab格式
func exportTasks(db *gorm.DB, group string, exportAll bool, from, to time.Time) {
	var tasks []model.Task
	query := db

	// 应用过滤条件
	if group != "" {
		query = query.Where("group_name = ?", group)
	}
	if !exportAll {
		query = query.Where("status = ?", 1)
	}
	if !from.IsZero() {
		query = query.Where("created_at >= ?", from)
	}
	if !to.IsZero() {
		query = query.Where("created_at <= ?", to)
	}

	if err := query.Find(&tasks).Error; err != nil {
		log.Fatalf("查询任务失败: %v", err)
	}

	if len(tasks) == 0 {
		fmt.Println("# 没有找到符合条件的任务")
		return
	}

	// 写入crontab格式的内容
	fmt.Println("# 由 CronGo 导出的定时任务")
	fmt.Printf("# 导出时间: %s\n", time.Now().Format("2006-01-02 15:04:05"))
	if group != "" {
		fmt.Printf("# 任务分组: %s\n", group)
	}
	if !from.IsZero() || !to.IsZero() {
		fmt.Printf("# 创建时间范围: %s", from.Format("2006-01-02"))
		if !to.IsZero() {
			fmt.Printf(" 至 %s", to.Format("2006-01-02"))
		}
		fmt.Println()
	}
	if exportAll {
		fmt.Println("# 包含所有状态的任务（禁用的任务会被注释）")
	}
	fmt.Println("#")

	for _, task := range tasks {
		// 如果有描述，先输出描述作为注释
		if task.Description != "" {
			fmt.Printf("# %s\n", task.Description)
		}
		// 输出任务的基本信息
		status := "启用"
		if task.Status != 1 {
			status = "禁用"
		}
		fmt.Printf("# 任务ID: %d, 名称: %s, 状态: %s\n", task.ID, task.Name, status)

		// 如果任务是禁用状态，在命令行前加上注释符号
		if task.Status != 1 {
			fmt.Printf("#%s %s\n\n", task.CronExpr, task.Command)
		} else {
			fmt.Printf("%s %s\n\n", task.CronExpr, task.Command)
		}
	}
}
